package cn.hashq.netpoststation.handler.map;

import cn.hashq.netpoststation.cache.ChannelCache;
import cn.hashq.netpoststation.dto.ProtoMsg;
import cn.hashq.netpoststation.entity.Client;
import cn.hashq.netpoststation.entity.PortMap;
import cn.hashq.netpoststation.session.ServerSession;
import cn.hashq.netpoststation.session.SessionMap;
import com.google.protobuf.ByteString;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;

/**
 * 映射端口数据处理Handler
 *
 * @author HashQ
 * @since 1.0
 */
@Slf4j
public class PortMapDataHandler extends ChannelInboundHandlerAdapter {

    private PortMap portMap;

    public PortMapDataHandler(PortMap port) {
        if (port == null) {
            log.error("port map not be null");
            throw new RuntimeException("port map not be null");
        }
        this.portMap = port;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        if (ctx.channel().isActive()) {
            log.info("服务端映射端口建立TCP连接,连接Id:{}", ctx.channel().id().asLongText());
            ChannelCache.getInstance().addChannel(ctx.channel());
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        ProtoMsg.Message msg = ProtoMsg.Message.newBuilder()
                .setType(ProtoMsg.HeadType.PORT_CONNECT_BREAK)
                .setSessionId(ctx.channel().id().asLongText())
                .build();
        ServerSession session = SessionMap.inst().getSession(portMap.getClientId());
        if (Objects.nonNull(session)) {
            session.writeAndFlush(msg);
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        String channelId = ctx.channel().id().asLongText();
        Long clientId = portMap.getClientId();
        ServerSession session = SessionMap.inst().getSession(clientId);
        if (Objects.isNull(session)) {
            log.info("[{}]对应客户端未上线", portMap.getName());
            ChannelCache.getInstance().removeChannel(channelId);
        }
        ByteBuf buf = (ByteBuf) msg;
        int length = buf.readableBytes();
        if (length == 0) {
            super.channelRead(ctx, msg);
            return;
        }
        byte[] bytes = new byte[length];
        buf.readBytes(bytes);
        ProtoMsg.DataPackage dataPackage = ProtoMsg.DataPackage.newBuilder()
                .setServerPort(portMap.getServerPort())
                .setClientPort(portMap.getClientPort())
                .setBytes(ByteString.copyFrom(bytes))
                .build();
        ProtoMsg.Message message = ProtoMsg.Message.newBuilder()
                .setSessionId(channelId)
                .setType(ProtoMsg.HeadType.SERVER_DATA_REDIRECT)
                .setDataPackage(dataPackage)
                .build();
        session.writeAndFlush(message);
    }
}
